const NUM1 = 1,
    NUM12 = 12,
    NUM7 = 7,
    ONESECOND = 1000,
    ONEMINUTE = 60000,
    ONEHOUR = 3600000;
export const ONEDAY = 86400000;
const BLANK_STRING = '';

/*
    格式化年月日
        date Date对象
        symbol 分隔符
        option 配置 控制是否展示年、月、日

        return String
*/
export const formatDate = (
    date = new Date(),
    symbol = '-',
    option = {
        YYYY: true,
        MM: true,
        DD: true,
    }
) => {
    const option_ = JSON.parse(JSON.stringify(option));
    option_.YYYY = option_.YYYY === undefined ? true : option_.YYYY;
    option_.MM = option_.MM === undefined ? true : option_.MM;
    option_.DD = option_.DD === undefined ? true : option_.DD;

    const YYYY = option_.YYYY ? date.getFullYear() : BLANK_STRING;
    const MM = option_.MM ? fill_00(date.getMonth() + NUM1) : BLANK_STRING;
    const DD = option_.DD ? fill_00(date.getDate()) : BLANK_STRING;

    const ARR = [YYYY, MM, DD];
    let res = BLANK_STRING;
    ARR.forEach((v, i) => {
        if (v !== BLANK_STRING) {
            if (res === BLANK_STRING) {
                res += v;
            } else {
                res += `${symbol}${v}`;
            }
        }
    });

    return res;
};
/*
    格式化时分秒
        date Date对象
        symbol 分隔符
        option 配置 控制是否展示时、分、秒

        return String
*/
export const formatTime = (
    date = new Date(),
    symbol = ':',
    option = {
        H: true,
        M: true,
        S: true,
    }
) => {
    const option_ = JSON.parse(JSON.stringify(option));
    option_.H = option_.H === undefined ? true : option_.H;
    option_.M = option_.M === undefined ? true : option_.M;
    option_.S = option_.S === undefined ? true : option_.S;

    const H = option_.H ? fill_00(date.getHours()) : BLANK_STRING;
    const M = option_.M ? fill_00(date.getMinutes()) : BLANK_STRING;
    const S = option_.S ? fill_00(date.getSeconds()) : BLANK_STRING;

    const ARR = [H, M, S];
    let res = BLANK_STRING;
    ARR.forEach((v, i) => {
        if (v !== BLANK_STRING) {
            if (res === BLANK_STRING) {
                res += v;
            } else {
                res += `${symbol}${v}`;
            }
        }
    });

    return res;
};
/*
    formatDate 反向操作
*/
export const formatDate_ = (
    str: string,
    symbol = '-',
    option = {
        YYYY: true,
        MM: true,
        DD: true,
    }
) => {
    const option_ = JSON.parse(JSON.stringify(option));
    option_.YYYY = option_.YYYY === undefined ? true : option_.YYYY;
    option_.MM = option_.MM === undefined ? true : option_.MM;
    option_.DD = option_.DD === undefined ? true : option_.DD;

    const arr = str.split(symbol);

    const { YYYY, MM, DD } = option_;

    let YYYY_, MM_, DD_;
    if (YYYY) {
        YYYY_ = arr.shift();
    }
    if (MM) {
        MM_ = arr.shift();
    }
    if (DD) {
        DD_ = arr.shift();
    }
    const now = new Date();
    return new Date(
        YYYY_ === undefined ? now.getFullYear() : Number(YYYY_),
        MM_ === undefined ? now.getMonth() : Number(MM_) - NUM1,
        DD_ === undefined ? now.getDate() : Number(DD_),
        0,
        0,
        0,
        0
    );
};

/*
    返回星期几
        return '星期几'
*/
export const getCnDay = () => {
    const day = new Date().getDay();
    let dayCn = '星期';
    switch (day) {
        case 0: {
            dayCn += '日';
            break;
        }
        case 1: {
            dayCn += '一';
            break;
        }
        case 2: {
            dayCn += '二';
            break;
        }
        case 3: {
            dayCn += '三';
            break;
        }
        case 4: {
            dayCn += '四';
            break;
        }
        case 5: {
            dayCn += '五';
            break;
        }
        case 6: {
            dayCn += '六';
            break;
        }
    }
    return dayCn;
};

/*
    N年前/后
        n 几年 正数 后，负数 前
        date 相對日期

        return Date
*/
const jumpYear = (n: number, date = new Date()) => {
    const year = date.getFullYear() + n;
    return new Date(new Date(date.getTime()).setFullYear(year));
};
/*
    N月前/后
        n 几月 正数 后，负数 前
        date 相對日期

        return Date
*/
export const jumpMonth = (n: number, date = new Date()) => {
    // nowM 现在的月份
    const nowM = date.getMonth() + NUM1;
    // allM 不进行12进制递增的月数
    const allM = n + nowM;
    // newM 新的月份
    const newM = (allM % NUM12) - NUM1;
    const years_ = allM / NUM12;
    // years 需要改变的年数
    let years;
    if (years_ === 0) {
        years = -1;
    } else if (years_ > 0) {
        years = Number.isInteger(years_) ? years_ - NUM1 : Math.ceil(years_) - NUM1;
    } else {
        years = Number.isInteger(years_) ? years_ - NUM1 : Math.floor(years_);
    }

    const newDate = new Date(date.getTime());
    newDate.setMonth(newM);
    newDate.setFullYear(date.getFullYear() + years);
    return newDate;
};
/*
    N周前/后
        n 几周 正数 后，负数 前
        date 相對日期

        return Date
*/
export const jumpWeek = (n: number, date = new Date()) =>
    new Date(date.getTime() + n * NUM7 * ONEDAY);
/*
    N天前/后
        n 几天 正数 后，负数 前
        date 相對日期

        return Date
*/
export const jumpDay = (n: number, date = new Date()) => new Date(date.getTime() + n * ONEDAY);
/*
    N小时前/后
        n 几小时 正数 后，负数 前
        date 相對日期

        return Date
*/
export const jumpHour = (n: number, date = new Date()) => new Date(date.getTime() + n * ONEHOUR);
/*
    N分钟前/后
        n 几分钟 正数 后，负数 前
        date 相對日期

        return Date
*/
export const jumpMinutes = (n: number, date = new Date()) =>
    new Date(date.getTime() + n * ONEMINUTE);
/*
    N秒钟前/后
        n 几秒钟 正数 后，负数 前
        date 相對日期

        return Date
*/
export const jumpSeconds = (n: number, date = new Date()) =>
    new Date(date.getTime() + n * ONESECOND);

/*
    向前距离当前最近的周几
        n 周几 0 ~ 6  日 ~ 六
        date 相對日期
        
        return Date
*/
export const nearCurrentWeekN = (n: number, date = new Date()) => {
    const week = date.getDay();
    if (week === n) {
        return date;
    } else {
        let nums;
        if (week < n) {
            const week_ = week + NUM1;
            const n_ = n + NUM1;
            nums = NUM7 - n_ + week_;
        } else {
            nums = week - n;
        }
        return new Date(date.getTime() - nums * ONEDAY);
    }
};

/*
    填充满两位数
        date Date对象
        symbol 分隔符
        option 配置 控制是否展示时、分、秒

        return String
*/
export const fill_00 = (n: number) => {
    const n_ = n.toString();
    return n_.length === NUM1 ? `0${n_}` : n_;
};

/*
    检查是否为 Invalid Date
*/
export const isInvalidDate = (date: Date) => {
    return date instanceof Date && !isNaN(date.getTime());
};
